package zack.project.domain.strategy.service.rule.chain.factory;

import zack.project.domain.strategy.adapter.repository.IStrategyRepository;
import zack.project.domain.strategy.model.entity.StrategyEntity;
import zack.project.domain.strategy.service.rule.chain.ILogicChain;
import lombok.*;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author A1793
 */
@Service
public class DefaultChainFactory {

   private final  IStrategyRepository repository;

   private final  ApplicationContext applicationContext;

   private final  Map<Long,ILogicChain> logicChainGroup;

    public DefaultChainFactory(ApplicationContext applicationContext, IStrategyRepository strategyRepository) {
        this.applicationContext = applicationContext;
        this.repository = strategyRepository;
        this.logicChainGroup = new ConcurrentHashMap<>();
    }

    /**
     * 装配责任链，返回并将该责任链头节点存入缓存
     * 根据数据库配置的rule_models,在容器中查找对应的责任链节点并装配
     * @param strategyId
     * @return
     */
    public ILogicChain openLogicChain(Long strategyId){

        ILogicChain cacheLogicChain = logicChainGroup.get(strategyId);
        if(cacheLogicChain != null){
            return cacheLogicChain;
        }
        //查找数据库是否配置了该strategyId有对应的责任链,数据库表:{strategy},查询strategyId对应的{rule_models}
        StrategyEntity strategyEntity = repository.queryStrategyEntityByStrategyId(strategyId);

        String[] ruleModels = strategyEntity.ruleModels();
        //如果规则为空或长度是0则装配默认的责任链节点
        if(ruleModels == null||ruleModels.length == 0) {
            ILogicChain ruleDefault = applicationContext.getBean(LogicModel.RULE_DEFAULT.code,
                    ILogicChain.class);
            logicChainGroup.put(strategyId, ruleDefault);
            return ruleDefault;
        }
        //在applicationContext中根据@Component中设置的beanName去查找对应的责任链节点
        ILogicChain logicChain = applicationContext.getBean(ruleModels[0], ILogicChain.class);
        ILogicChain cur = logicChain;
        for(int i = 1; i < ruleModels.length; i++){
            ILogicChain next = applicationContext.getBean(ruleModels[i], ILogicChain.class);
            cur = cur.appendNext(next);
        }
        cur.appendNext(applicationContext.getBean(LogicModel.RULE_DEFAULT.code, ILogicChain.class));
        //缓存当前strategyId对应的责任链
        logicChainGroup.put(strategyId,logicChain);
        return logicChain;
    }



    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class StrategyAwardVO{

        /** 抽奖奖品ID - 内部流转使用 */
        private Integer awardId;
        /** 奖品来自责任链的哪个节点 */
        private String logicModel;

        private String awardRuleValue;

    }
    @Getter
    @AllArgsConstructor
    public enum LogicModel {

        RULE_DEFAULT("rule_default", "默认抽奖"),
        RULE_BLACKLIST("rule_blacklist", "黑名单抽奖"),
        RULE_WEIGHT("rule_weight", "权重规则"),
        ;

        private final String code;
        private final String info;

    }


}
